<template>
  <div :style="getContainerStyle()" class="upload-container">
    <div v-if="showTitle" :style="getTitleStyle()" :class="required ? 'required' : ''" class="upload-title">{{ title }}</div>
    <div class="img-container clearfix">
      <div v-for="img in uploadArray" :key="img.id" class="img">
        <img v-if="img.path" :src="util.getUrl('/' + img.path)">
        <div v-if="!img.uploading && mode !== 'readonly'" class="close" @click="close(img)">×</div>
        <img v-if="img.uploading" class="loading" src="@i/loading.gif">
        <div v-if="!img.uploading && mode !== 'readonly'" class="operation-container">
          <div @click="toEdit(img)">编辑</div>
          <div v-show="ablePreview" @click="preview(img)">预览</div>
        </div>
      </div>
      <div class="img add" :class="uploadArray.length >= maxCount || currentMode === 'readonly' ? 'hide' : ''" @click="toUpload">
        <div/>
        <div class="tip-container">
          <div class="to-add">点击添加图片</div>
          <div class="desc">
            <slot name="desc">
              <div>支持{{validTypes.join('，')}}格式</div>
              <div>最多上传{{maxCount}}张图片</div>
              <div>每张图片不超过{{maxSize / 1024 / 1024}}MB</div>
            </slot>
          </div>
        </div>
      </div>
      <form :id="formId">
        <input :id="fileId" :accept="accept" type="file" class="hide" @change="onChange">
      </form>
    </div>
  </div>
</template>

<script>
import uuid from 'uuid'
import axios from 'axios'

export default {
  computed: {
    validTypes() {
      let validTypes = this.objectUtil.copyObject(this.accept).replace(/image\//g, '').split(',')
      return validTypes
    }
  },
  props: {
    data: {
      type: Array,
      default: () => []
    },
    accept: {
      type: String,
      default: 'image/jpg,image/jpeg,image/png'
    },
    maxCount: {
      type: Number,
      default: 10
    },
    maxSize: {
      type: Number,
      default: 5 * 1024 * 1024
    },
    // 是否可以预览
    ablePreview: {
      type: Boolean,
      default: true
    },
    title: {
      type: String,
      default: ''
    },
    titleStyle: {
      type: Object,
      default: null
    },
    containerStyle: {
      type: Object,
      default: null
    },
    titleCount: {
      type: Number,
      default: 0
    },
    showTitle: {
      type: Boolean,
      default: true
    },
    mode: {
      type: String,
      default: 'edit'
    },
    required: {
      type: Boolean,
      default: false
    }
  },
  data() {
    let that = this
    let idString = uuid()
    return {
      formId: `form-${idString}`,
      fileId: `file-${idString}`,
      // 待修改的图片id
      editIndex: null,
      file: '',
      form: '',
      uploadArray: that.getUploadArray(that.data),
      // 默认新增 edit readonly
      currentMode: this.mode
    }
  },
  watch: {
    data: {
      deep: true,
      handler(newValue) {
        this.uploadArray = this.getUploadArray(newValue)
      }
    }
  },
  mounted() {
    this.form = window.document.getElementById(this.formId)
    this.file = window.document.getElementById(this.fileId)
  },
  methods: {
    onChange(e) {
      let files = e.target.files
      let file = files[0]
      let validTypes = this.objectUtil.copyObject(this.accept).replace(/image\//ig, '').split(',')
      if (file) {
        let type = file.type.split('/')[1]
        if (validTypes.indexOf(type) == -1) {
          this.tipUtil.warning('请上传图片格式的文件!')
          this.form.reset()
          return
        }

        let maxSize = this.maxSize
        // 当maxSize!=0时，需要校验
        if (maxSize && file.size > maxSize) {
          this.tipUtil.warning(`图片大小不能超过${maxSize / 1024 / 1024}M`)
          return
        }
        this.upload(file, this.editIndex)
      }
    },
    // 本地上传
    showUpload() {
      this.files = []
      this.form.reset()
      this.file.click()
    },
    toEdit(img) {
      if (this.currentMode === 'readonly') {
        return
      }

      if (img.uploading) {
        this.tipUtil.warning('图片正在上传中，请稍后再操作')
        return
      }

      this.editIndex = img.id
      this.currentMode = 'edit'
      // 如果是指定的imageType，可以从图片库中选择图片
      this.showUpload()
    },
    close(img) {
      if (img.uploading) {
        this.tipUtil.warning('图片正在上传中，请稍后再操作')
        return
      }

      this.uploadArray.splice(this.uploadArray.indexOf(img), 1)
      this.toEmit()
    },
    toUpload() {
      if (this.currentMode === 'readonly') {
        return
      }

      if (this.uploadArray.length >= this.maxCount) {
        this.tipUtil.warning(`最多只能上传${this.maxCount}张图片`)
        return
      }

      this.editIndex = null
      this.currentMode = 'add'
      this.showUpload()
    },
    upload(file, id) {
      let _id = id
      if (!window.FormData) {
        this.tipUtil.warning('浏览器版本太低')
        return
      }

      if (!_id) {
        _id = uuid()
        this.uploadArray.push({
          id: _id,
          path: '',
          uploading: true
        })
      }

      let config = {
        headers: {
          'Content-Type': 'multipart/form-data',
          Token: this.util.getToken()
        }
      }

      let form = new FormData()
      form.append('File', file)

      this.changeStatus(_id, true)
      api.upload(form).then(res => {
        let exist = false
        let array = this.uploadArray
        let img = {
          id: _id,
          path: res.Data,
          uploading: false,
          // 本地上传
          fromLocal: true
        }
        for (let i = 0; i < array.length; i++) {
          let item = array[i]
          // 修改
          if (item.id === _id) {
            this.uploadArray.splice(i, 1, img)
            exist = true
            break
          }
        }

        // 新增
        if (!exist) {
          this.uploadArray.push(img)
        }

        this.toEmit()
      }).catch(error => {
        this.changeStatus(_id, false)
        this.removeItem(_id)
      })
    },
    removeItem(id) {
      let arr = this.uploadArray
      for (let i = 0; i < arr.length; i++) {
        if (id === arr[i].id) {
          arr.splice(i, 1)
          break
        }
      }
    },

    /* pcStyle、mobileStyle */
    getTitleStyle() {
      let style = this.titleStyle
      if (style) {
        return style.pcStyle
      } else {
        let titleCount = this.titleCount
        if (!this.isMobile) {
          return {
            width: `${titleCount * 12}px`
          }
        } else {
          return {
            width: `${titleCount * 12}px`
          }
        }
      }
    },
    getContainerStyle() {
      let style = this.containerStyle
      if (style) {
        return style.pcStyle
      } else {
        let titleCount = this.titleCount
        if (!this.isMobile) {
          return {
            'padding-left': `${titleCount * 12}px`
          }
        } else {
          return {
            'padding-left': `${titleCount * 12}px`
          }
        }
      }
    },
    getUploadArray(list) {
      let array = []
      list.forEach(item => {
        array.push({
          id: uuid(),
          path: item.path,
          uploading: false
        })
      })
      return array
    },
    changeStatus(id, uploading) {
      let list = this.uploadArray
      for (let i = 0; i < list.length; i++) {
        let item = list[i]
        let path = item.path
        // 修改
        if (item.id === id) {
          this.uploadArray.splice(i, 1, {
            id,
            path,
            uploading
          })
          break
        }
      }
    },
    toEmit() {
      let newFiles = []
      this.uploadArray.forEach(item => {
        let path = item.path
        if (path) {
          newFiles.push({
            path,
            // 是否是本地上传
            fromLocal: item.fromLocal
          })
        }
      })

      this.$emit('update:data', newFiles)
    },
    preview(img) {
      this.$emit('previewImg', img.path)
    }
  }
}
</script>

<style scoped lang="less">
.upload-container {
  position: relative;
  .upload-title {
    font-size: 12px;
    padding: 10px 12px 10px 0;
    position: absolute;
    text-align: right;
    left: 0;
    top: 0;
  }
  .img-container {
    min-height: 180px;
    .img {
      float: left;
      cursor: pointer;
      font-size: 20px;
      width: 240px;
      height: 180px;
      border: 1px solid #e1e3e6;
      position: relative;
      margin-bottom: 10px;
      overflow: hidden;
      &:not(:last-child) {
        margin-right: 10px;
      }
      > img:first-child {
        width: 100%;
        height: 100%;
      }
      .close {
        position: absolute;
        top: 0;
        right: 0;
        width: 20px;
        height: 20px;
        line-height: 20px;
        font-size: 20px;
        text-align: center;
        color: #fff;
        z-index: 1000;
        img {
          width: 10px;
          height: 10px;
          position: absolute;
          top: 5px;
          right: 5px;
        }
      }
      .loading {
        position: absolute;
        width: 30px !important;
        height: 30px !important;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
        z-index: 3;
      }
      &:hover {
        .operation-container {
          transform: translateY(0);
        }
        .close {
          &:hover {
            color: red;
          }
        }
      }
      .operation-container {
        line-height: 40px;
        background: #fff;
        position: absolute;
        left: 0;
        right: 0;
        bottom: 0;
        transform: translateY(50px);
        transition: transform ease .5s;
        z-index: 100;
        display: flex;
        > div {
          flex: 1;
          text-align: center;
          font-size: 14px;
          color: #f00;
          cursor: pointer;
          position: relative;
          &:not(:first-child):before {
            content: '';
            width: 1px;
            position: absolute;
            left: 0;
            top: 5px;
            bottom: 5px;
            background: #ccc;
          }
        }
      }
      &.add {
        padding: 30px 0 0;
        background:rgba(242,242,242,1);
        border-radius:2px;
        > div:first-child {
          width: 32px;
          height: 32px;
          margin: 0 auto;
          background: @primary-color;
          border-radius: 50%;
          position: relative;
          &:before {
            content: '+';
            color: #fff;
            font: 20px Arial;
            position: absolute;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
          }
        }
        .tip-container {
          margin-top: 10px;
          text-align: center;
          .to-add {
            font-size:14px;
            
            font-weight:400;
            color:rgba(153,153,153,1);
            line-height:20px;
          }
          .desc {
            margin-top: 6px;
            > div {
              font-size:12px;
              
              font-weight:400;
              color:rgba(187,187,187,1);
              line-height:17px;
            }
          }
        }
      }
    }
  }
}
</style>